/* ------------------------------------------------------------------------*
 *
 * ------------------------------------------------------------------------*/
#include "stdint.h"
#include "os_obj.h"
#include "systask.h"
#include "bsp.h"

#include "nor_cmd.h"
#include "bsp_spi_nor.h"
#include "simp_log2_ext.h"

#include "str_ext.h"
#include "common.h"
/*****************************************************************************
* @brief   delay .
*****************************************************************************/

static void LogErase(uint32_t AddrBase);             /*从指定地址擦除，Nums指定擦除的扇区个数*/
static void LogProgram(uint32_t Addr, uint32_t *Data, uint16_t Len); /*向指定指定地址编程数据*/
static void LogRead(uint32_t Addr, uint32_t *Data, uint16_t Len);    /*读取块数据*/

// 日志数据
typedef struct
{
	sig_time_type time;
	uint16_t temp_pv;
	uint16_t temp_sv;
	uint16_t humi_pv;
	uint16_t humi_sv;
	uint16_t ver[24];
} log_dat_type;

static log_dat_type log_dat;

// 日志缓存配置
simp_log2_ext_api_ref(log2_cfg);
simp_log2_info_type log2_info;

simp_log2_type  log2_cfg =
{
	.addr_base = 256 * 1024,
	.total_size = 32 * 1024,
	.page_size = 4 * 1024,
	.dat_size = 48,
	.pdat = (uint8_t*)&log_dat,
	.info = &log2_info,
	.Erase = LogErase,
	.Program = LogProgram,
	.Read = LogRead,
	.api = simp_log2_api_name(log2_cfg)
};

simp_log2_ext_api_make(log2_cfg);

// 日志缓存管理
typedef struct
{
	int32_t search_res;
	sig_time_type sig_time;
	TIME_Type rtc_time;
	log_dat_type log_rd;
	uint16_t save_req;
	uint16_t read_req;
	uint8_t clr_req;
	uint8_t alain_req;
	int8_t tm_search_req;
	uint8_t hd_search_req;
	uint8_t init_req;
	uint32_t start_addr;
	uint32_t next_addr;
	uint32_t res_addr;
} log_buff_test_type;

log_buff_test_type simp_log_obj;

/*-----------------------------------------------------------------------------------------------------*
* log_buff_test
*-----------------------------------------------------------------------------------------------------*/
void simp_log_test(void)
{
	gd25_dbg_puts("switch to log buffer test module \n");

	// 设置时间
	rtc_time_run_sec(&simp_log_obj.rtc_time, 30);
	rtc_time_run_min(&simp_log_obj.rtc_time, 360);
	rtc_time_run_hour(&simp_log_obj.rtc_time, 15*366*24);

	log2_cfg.api->init();

	if (log2_cfg.info->site_next > 0)
	{
		log_dat.time.val = inpw(log2_cfg.api->site_to_addr(log2_cfg.info->site_next - 1));
		time_sig_to_time(log_dat.time, &simp_log_obj.rtc_time);
	}

	for (;;)
	{
		if(sys_st.str_module != 7)
			break;
		
		osDelay(ms_ticks(10));

		simp_log_obj.start_addr = log2_cfg.api->site_to_addr(log2_cfg.info->site_start);
		simp_log_obj.next_addr = log2_cfg.api->site_to_addr(log2_cfg.info->site_next);
		simp_log_obj.res_addr = log2_cfg.api->site_to_addr(simp_log_obj.search_res);
		
		// 清除日志缓存
		if (simp_log_obj.clr_req)
		{
			loop_n(8)
			{
				LogErase(log2_cfg.addr_base + 4 * index * 1024);
			}
			
			log2_cfg.api->init();
			simp_log_obj.clr_req = 0;
		}

		// 保存日志
		if (simp_log_obj.save_req)
		{
			simp_log_obj.save_req--;
			rtc_time_run_min(&simp_log_obj.rtc_time, 2);
			log_dat.time = time_to_sig(&simp_log_obj.rtc_time);
			log_dat.temp_pv = (log_dat.temp_pv + 3) & 0x7FF;
			log_dat.humi_pv = (log_dat.humi_pv + 5) & 0x3FF;
			log2_cfg.api->save();
		}

		// 读取一条日志
		if(simp_log_obj.read_req)
		{
			log2_cfg.api->read(simp_log_obj.read_req, &simp_log_obj.log_rd);
			simp_log_obj.read_req = 0;
		}

		// 初始化
		if (simp_log_obj.init_req)
		{
			simp_log_obj.init_req = 0;
			log2_cfg.api->init();
		}

		// 搜索
		if (simp_log_obj.tm_search_req)
		{
			if(simp_log_obj.tm_search_req  < 0)
				simp_log_obj.search_res = log2_cfg.api->quick_search(simp_log_obj.sig_time, -1);
			else
				simp_log_obj.search_res = log2_cfg.api->quick_search(simp_log_obj.sig_time, 1);
			simp_log_obj.tm_search_req = 0;
			
			simp_log_obj.read_req = simp_log_obj.search_res;
			
			gd25_dbg_print("log buff search res: 0x%x \n", simp_log_obj.search_res);
		}
		
		if(simp_log_obj.hd_search_req)
		{
			log2_cfg.api->head_search(simp_log_obj.hd_search_req, &simp_log_obj.search_res);
			simp_log_obj.hd_search_req = 0;
		}
	}
}

/*--------------------------------------------------------------------------------*
* log buff hal
*---------------------------------------------------------------------------------*/
void LogProgram(uint32_t Addr, uint32_t *Data, uint16_t Len)
{
	SYS_UnlockReg();
	FMC_Open();
	FMC_ENABLE_AP_UPDATE();

	Len /= 4;
	while (Len--)
	{
		FMC_Write(Addr, *Data);
		Addr += 4;
		Data ++;
	}

	FMC_DISABLE_AP_UPDATE();
	FMC_Close();
	SYS_LockReg();
}

void LogRead(uint32_t Addr, uint32_t *Data, uint16_t Len)
{
	Len /= 4;

	while (Len--)
	{
		*Data = inpw(Addr);;
		Addr += 4;
		Data ++;
	}
}

void LogErase(uint32_t AddrBase)
{
	int index;

	SYS_UnlockReg();
	FMC_Open();
	FMC_ENABLE_AP_UPDATE();

	for (index = 0; index < 4 * 1024 / FMC_FLASH_PAGE_SIZE; index++)
	{
		FMC_Erase(AddrBase + index * FMC_FLASH_PAGE_SIZE);
	}

	FMC_DISABLE_AP_UPDATE();
	FMC_Close();
	SYS_LockReg();
}
